// AlsaCore.cpp - Wrapper for ALSA library to record and play wave files

#include <iostream>
#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <time.h>
#include <locale.h>
#include <assert.h>
#include <termios.h>
#include <signal.h>
#include <output.h>
#include <sys/poll.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <asm/byteorder.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <libintl.h>
#include <endian.h>
#include <byteswap.h>
#include <math.h>
#include <pthread.h>
#include "gettext.h"
#include "formats.h"
#include "version.h"
#include "AlsaPlayers.h"

AlsaWaveFilePlayer::AlsaWaveFilePlayer()
{
}

AlsaWaveFilePlayer::~AlsaWaveFilePlayer()
{
}


int AlsaWaveFilePlayer::Play(char * filename)
{
#ifdef _DEBUG
    std::cout << "AlsaCore play file " << filename << "\n";
#endif

    char *pcm_name = (char *)"default";
    int err;
    snd_pcm_info_t *info = NULL;
    snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
    int open_mode = 0;
    int nonblock = 0;
    int mmap_flag = 0;
    FILE *pidf = NULL;

    file_type = FORMAT_DEFAULT;
    stream = SND_PCM_STREAM_PLAYBACK;
    command = (char *)"aplay";

    rhwparams.format = DEFAULT_FORMAT;
    rhwparams.rate = DEFAULT_SPEED;
    rhwparams.channels = 1;

    snd_pcm_info_alloca(&info);

    err = snd_output_stdio_attach(&loghandle, stderr, 0);
    assert(err >= 0);

    err = snd_pcm_open(&handle, pcm_name, stream, open_mode);
    if (err < 0) {
        error(_("audio open error: %s"), snd_strerror(err));
        return (1);
    }

    if ((err = snd_pcm_info(handle, info)) < 0) {
        error(_("info error: %s"), snd_strerror(err));
        return (1);
    }

    if (nonblock) {
        err = snd_pcm_nonblock(handle, 1);
        if (err < 0) {
            error(_("nonblock setting error: %s"), snd_strerror(err));
            return (1);
        }
    }

    chunk_size = DEFAULT_CHUNK_SIZE;
    hwparams = rhwparams;

    audiobuf = (unsigned char *)malloc(AUDIO_BUFFER_SIZE);
    if (audiobuf == NULL) {
        error(_("not enough memory"));
        return (1);
    }

    if (mmap_flag) {
        writei_func = snd_pcm_mmap_writei;
        readi_func  = snd_pcm_mmap_readi;
        writen_func = snd_pcm_mmap_writen;
        readn_func  = snd_pcm_mmap_readn;
    } else {
        writei_func = snd_pcm_writei;
        readi_func  = snd_pcm_readi;
        writen_func = snd_pcm_writen;
        readn_func  = snd_pcm_readn;
    }

    if (pidfile_name) {
        errno = 0;
        pidf = fopen(pidfile_name, "w");
        if (pidf) {
            (void)fprintf (pidf, "%d\n", getpid());
            fclose(pidf);
            pidfile_written = 1;
        } else {
            error(_("Cannot create process ID file %s: %s"),
                    pidfile_name, strerror (errno));
            return (1);
        }
    }

    //todo:
    /*
    signal(SIGINT,  signal_handler);
    signal(SIGTERM, signal_handler);
    signal(SIGABRT, signal_handler);
    signal(SIGUSR1, signal_handler_recycle);
    */

    playback(filename);

    if (verbose == 2) {
        putchar('\n');
    }

    snd_pcm_close(handle);
    handle = NULL;
    free(audiobuf);

    snd_output_close(loghandle);
    snd_config_update_free_global();

    return (EXIT_SUCCESS);
}
